/**
 * MySQL EXPLAIN 解析器
 * 支持多种格式：Tree、JSON、Traditional
 */
class ExplainParser {
    constructor() {
        this.nodeIdCounter = 0;
    }

    /**
     * 自动检测输入格式并解析
     */
    parse(input) {
        if (!input || typeof input !== 'string') {
            throw new Error('输入数据不能为空');
        }

        const trimmedInput = input.trim();
        
        // 检测格式
        const format = this.detectFormat(trimmedInput);
        
        // 根据格式解析
        switch (format) {
            case 'tree':
                return this.parseTreeFormat(trimmedInput);
            case 'json':
                return this.parseJsonFormat(trimmedInput);
            case 'traditional':
                return this.parseTraditionalFormat(trimmedInput);
            default:
                throw new Error('无法识别的EXPLAIN格式');
        }
    }

    /**
     * 检测输入格式
     */
    detectFormat(input) {
        // JSON格式检测
        if (input.startsWith('{') || input.startsWith('[')) {
            try {
                JSON.parse(input);
                return 'json';
            } catch (e) {
                // 不是有效的JSON
            }
        }

        // Tree格式检测 (以 -> 开头)
        if (input.includes('->') && input.includes('cost=')) {
            return 'tree';
        }

        // Traditional格式检测 (包含表格分隔符)
        if (input.includes('+---') || input.includes('| id |')) {
            return 'traditional';
        }

        // 默认尝试Tree格式
        return 'tree';
    }

    /**
     * 解析Tree格式
     */
    parseTreeFormat(input) {
        const lines = input.split('\n').filter(line => line.trim());
        const root = this.parseTreeNode(lines, 0);
        
        return {
            format: 'tree',
            root: root.node,
            stats: this.calculateStats(root.node)
        };
    }

    /**
     * 解析Tree节点
     */
    parseTreeNode(lines, startIndex) {
        if (startIndex >= lines.length) {
            return { node: null, nextIndex: startIndex };
        }

        const line = lines[startIndex];
        const indent = this.getIndentLevel(line);
        const cleanLine = line.trim().replace(/^->/, '').trim();
        
        // 解析节点信息
        const node = this.parseTreeLine(cleanLine);
        node.id = `node_${++this.nodeIdCounter}`;
        node.children = [];

        let nextIndex = startIndex + 1;
        
        // 解析子节点
        while (nextIndex < lines.length) {
            const nextLine = lines[nextIndex];
            const nextIndent = this.getIndentLevel(nextLine);
            
            // 如果缩进级别相同或更小，说明不是子节点
            if (nextIndent <= indent) {
                break;
            }
            
            // 如果是直接子节点（缩进级别正好大一级）
            if (nextIndent === indent + 4) {
                const childResult = this.parseTreeNode(lines, nextIndex);
                if (childResult.node) {
                    node.children.push(childResult.node);
                }
                nextIndex = childResult.nextIndex;
            } else {
                nextIndex++;
            }
        }

        return { node, nextIndex };
    }

    /**
     * 获取行的缩进级别
     */
    getIndentLevel(line) {
        const match = line.match(/^(\s*)/);
        return match ? match[1].length : 0;
    }

    /**
     * 解析Tree格式的单行
     */
    parseTreeLine(line) {
        const node = {
            node_type: 'unknown',
            label: line,
            performance_metrics: {
                cost: 0,
                rows: 0,
                execution_time: null,
                filtered: 100.0
            },
            index_info: {
                key: null,
                key_len: null,
                used_key_parts: []
            },
            access_type: null,
            warnings: [],
            suggestions: []
        };

        // 解析成本信息
        const costMatch = line.match(/cost=([0-9.]+)/);
        if (costMatch) {
            node.performance_metrics.cost = parseFloat(costMatch[1]);
        }

        // 解析行数信息
        const rowsMatch = line.match(/rows=([0-9]+)/);
        if (rowsMatch) {
            node.performance_metrics.rows = parseInt(rowsMatch[1]);
        }

        // 解析执行时间
        const timeMatch = line.match(/time=([0-9.]+)/);
        if (timeMatch) {
            node.performance_metrics.execution_time = parseFloat(timeMatch[1]);
        }

        // 确定节点类型和标签
        node.node_type = this.determineNodeType(line);
        node.label = this.extractNodeLabel(line);

        // 检查性能警告
        node.warnings = this.checkWarnings(line);
        
        return node;
    }

    /**
     * 解析JSON格式
     */
    parseJsonFormat(input) {
        try {
            const jsonData = JSON.parse(input);
            const root = this.convertJsonToNode(jsonData);
            
            return {
                format: 'json',
                root: root,
                stats: this.calculateStats(root)
            };
        } catch (error) {
            throw new Error('JSON格式解析失败: ' + error.message);
        }
    }

    /**
     * 将JSON数据转换为节点
     */
    convertJsonToNode(jsonData) {
        const node = {
            id: `node_${++this.nodeIdCounter}`,
            node_type: 'query_block',
            label: 'Query Block',
            performance_metrics: {
                cost: 0,
                rows: 0,
                execution_time: null,
                filtered: 100.0
            },
            index_info: {
                key: null,
                key_len: null,
                used_key_parts: []
            },
            access_type: null,
            warnings: [],
            suggestions: [],
            children: []
        };

        // 处理query_block
        if (jsonData.query_block) {
            const qb = jsonData.query_block;
            
            // 提取成本信息
            if (qb.cost_info && qb.cost_info.query_cost) {
                node.performance_metrics.cost = parseFloat(qb.cost_info.query_cost);
            }

            // 处理表信息
            if (qb.table) {
                const tableNode = this.convertTableToNode(qb.table);
                node.children.push(tableNode);
            }

            // 处理嵌套循环连接
            if (qb.nested_loop) {
                qb.nested_loop.forEach(item => {
                    if (item.table) {
                        const tableNode = this.convertTableToNode(item.table);
                        node.children.push(tableNode);
                    }
                });
            }
        }

        return node;
    }

    /**
     * 将表信息转换为节点
     */
    convertTableToNode(tableData) {
        const node = {
            id: `node_${++this.nodeIdCounter}`,
            node_type: 'table_scan',
            label: `Table: ${tableData.table_name || 'unknown'}`,
            performance_metrics: {
                cost: 0,
                rows: tableData.rows_examined_per_scan || 0,
                execution_time: null,
                filtered: parseFloat(tableData.filtered || 100)
            },
            index_info: {
                key: tableData.key || null,
                key_len: tableData.key_length || null,
                used_key_parts: []
            },
            access_type: tableData.access_type || 'ALL',
            warnings: [],
            suggestions: [],
            children: []
        };

        // 提取成本信息
        if (tableData.cost_info) {
            node.performance_metrics.cost = parseFloat(tableData.cost_info.read_cost || 0);
        }

        // 检查性能警告
        if (tableData.access_type === 'ALL') {
            node.warnings.push('Full table scan');
        }

        return node;
    }

    /**
     * 解析Traditional格式
     */
    parseTraditionalFormat(input) {
        const lines = input.split('\n').filter(line => line.trim());
        const dataLines = lines.filter(line => 
            line.includes('|') && 
            !line.includes('+---') && 
            !line.includes('| id |')
        );

        const nodes = dataLines.map(line => this.parseTraditionalLine(line));
        
        // 构建树结构
        const root = this.buildTreeFromTraditional(nodes);
        
        return {
            format: 'traditional',
            root: root,
            stats: this.calculateStats(root)
        };
    }

    /**
     * 解析Traditional格式的单行
     */
    parseTraditionalLine(line) {
        const parts = line.split('|').map(part => part.trim()).filter(part => part);
        
        if (parts.length < 10) {
            return null;
        }

        const node = {
            id: `node_${++this.nodeIdCounter}`,
            node_type: 'table_scan',
            label: `Table: ${parts[2]}`,
            performance_metrics: {
                cost: 0,
                rows: parseInt(parts[9]) || 0,
                execution_time: null,
                filtered: parseFloat(parts[10]) || 100
            },
            index_info: {
                key: parts[6] !== 'NULL' ? parts[6] : null,
                key_len: parts[7] !== 'NULL' ? parts[7] : null,
                used_key_parts: []
            },
            access_type: parts[4] || 'ALL',
            warnings: [],
            suggestions: [],
            children: []
        };

        // 检查Extra信息中的警告
        const extra = parts[11] || '';
        if (extra.includes('Using filesort')) {
            node.warnings.push('Using filesort');
        }
        if (extra.includes('Using temporary')) {
            node.warnings.push('Using temporary');
        }

        return node;
    }

    /**
     * 从Traditional格式构建树结构
     */
    buildTreeFromTraditional(nodes) {
        if (!nodes || nodes.length === 0) {
            return null;
        }

        // 简单处理：第一个节点作为根节点，其他作为子节点
        const root = nodes[0];
        root.children = nodes.slice(1);
        
        return root;
    }

    /**
     * 确定节点类型
     */
    determineNodeType(line) {
        const lowerLine = line.toLowerCase();
        
        if (lowerLine.includes('sort')) return 'sort';
        if (lowerLine.includes('nested loop')) return 'nested_loop_join';
        if (lowerLine.includes('hash join')) return 'hash_join';
        if (lowerLine.includes('index scan')) return 'index_scan';
        if (lowerLine.includes('index lookup')) return 'index_lookup';
        if (lowerLine.includes('filter')) return 'filter';
        if (lowerLine.includes('aggregate')) return 'aggregate';
        if (lowerLine.includes('group by')) return 'group_by';
        if (lowerLine.includes('distinct')) return 'distinct';
        if (lowerLine.includes('subquery')) return 'subquery';
        if (lowerLine.includes('materialize')) return 'materialize';
        if (lowerLine.includes('window')) return 'window_function';
        
        return 'table_scan';
    }

    /**
     * 提取节点标签
     */
    extractNodeLabel(line) {
        // 移除成本和行数信息，保留主要描述
        return line.replace(/\s*\(cost=[^)]+\)\s*$/, '').trim();
    }

    /**
     * 检查性能警告
     */
    checkWarnings(line) {
        const warnings = [];
        const lowerLine = line.toLowerCase();
        
        if (lowerLine.includes('filesort')) {
            warnings.push('Using filesort');
        }
        if (lowerLine.includes('temporary')) {
            warnings.push('Using temporary');
        }
        if (lowerLine.includes('full table scan')) {
            warnings.push('Full table scan');
        }
        
        return warnings;
    }

    /**
     * 计算统计信息
     */
    calculateStats(root) {
        if (!root) {
            return {
                totalCost: 0,
                nodeCount: 0,
                executionTime: null,
                rowsExamined: 0
            };
        }

        const stats = {
            totalCost: 0,
            nodeCount: 0,
            executionTime: null,
            rowsExamined: 0
        };

        this.traverseAndCalculate(root, stats);
        
        return stats;
    }

    /**
     * 遍历节点并计算统计信息
     */
    traverseAndCalculate(node, stats) {
        if (!node) return;

        stats.nodeCount++;
        stats.totalCost += node.performance_metrics.cost || 0;
        stats.rowsExamined += node.performance_metrics.rows || 0;
        
        if (node.performance_metrics.execution_time) {
            stats.executionTime = Math.max(stats.executionTime || 0, node.performance_metrics.execution_time);
        }

        if (node.children) {
            node.children.forEach(child => {
                this.traverseAndCalculate(child, stats);
            });
        }
    }

    /**
     * 重置节点ID计数器
     */
    resetNodeIdCounter() {
        this.nodeIdCounter = 0;
    }
}

// 示例数据
const EXAMPLE_DATA = {
    tree: `-> Sort: orders.create_time DESC  (cost=128.05 rows=999)
    -> Nested loop inner join  (cost=110.25 rows=999)
        -> Filter: (orders.status = 'active')  (cost=25.50 rows=500)
            -> Index scan on orders using idx_status  (cost=25.50 rows=500)
        -> Index lookup on users using PRIMARY (id=orders.user_id)  (cost=0.35 rows=2)`,
    
    json: `{
  "query_block": {
    "select_id": 1,
    "cost_info": {
      "query_cost": "128.05"
    },
    "ordering_operation": {
      "using_filesort": true,
      "nested_loop": [
        {
          "table": {
            "table_name": "orders",
            "access_type": "ref",
            "possible_keys": ["idx_status"],
            "key": "idx_status",
            "used_key_parts": ["status"],
            "key_length": "767",
            "ref": ["const"],
            "rows_examined_per_scan": 500,
            "rows_produced_per_join": 500,
            "filtered": "100.00",
            "cost_info": {
              "read_cost": "25.50",
              "eval_cost": "50.00",
              "prefix_cost": "75.50",
              "data_read_per_join": "39K"
            },
            "used_columns": ["id", "user_id", "status", "create_time"],
            "attached_condition": "(\`orders\`.\`status\` = 'active')"
          }
        },
        {
          "table": {
            "table_name": "users",
            "access_type": "eq_ref",
            "possible_keys": ["PRIMARY"],
            "key": "PRIMARY",
            "used_key_parts": ["id"],
            "key_length": "4",
            "ref": ["orders.user_id"],
            "rows_examined_per_scan": 1,
            "rows_produced_per_join": 500,
            "filtered": "100.00",
            "cost_info": {
              "read_cost": "125.00",
              "eval_cost": "50.00",
              "prefix_cost": "250.50",
              "data_read_per_join": "7K"
            }
          }
        }
      ]
    }
  }
}`,
    
    traditional: `+----+-------------+--------+------------+------+---------------+-----------+---------+------------------+------+----------+-----------------------------+
| id | select_type | table  | partitions | type | possible_keys | key       | key_len | ref              | rows | filtered | Extra                       |
+----+-------------+--------+------------+------+---------------+-----------+---------+------------------+------+----------+-----------------------------+
|  1 | SIMPLE      | orders | NULL       | ref  | idx_status    | idx_status| 767     | const            |  500 |   100.00 | Using where; Using filesort |
|  1 | SIMPLE      | users  | NULL       | eq_ref| PRIMARY      | PRIMARY   | 4       | orders.user_id   |    1 |   100.00 | NULL                        |
+----+-------------+--------+------------+------+---------------+-----------+---------+------------------+------+----------+-----------------------------+`
};

// 导出
window.ExplainParser = ExplainParser;
window.EXAMPLE_DATA = EXAMPLE_DATA;
